package com.kgc.scd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kgc.scd.bean.ShopGoods;
import com.kgc.scd.bean.ShopHistory;
import com.kgc.scd.mapper.ShopGoodsMapper;
import com.kgc.scd.mapper.ShopHistoryMapper;
import com.kgc.scd.service.ShopHistoryService;
import com.kgc.scd.util.PageSupport;
import com.kgc.scd.util.RedisUtils;
import com.kgc.scd.util.SnowUtil;
import com.kgc.scd.vo.ShopGoodsVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created On : 2022/11/14 0014.
 * <p>
 * Author : shiguangchuan
 * <p>
 * Description: 历史足迹业务接口实现类
 */
@Service
@Slf4j
public class ShopHistoryServiceImpl implements ShopHistoryService {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private SnowUtil snowUtil;

    @Autowired
    private ShopHistoryMapper shopHistoryMapper;

    @Autowired
    private ShopGoodsMapper shopGoodsMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public void updateHistoryData(String goodsId, String userId) {

        // 封装需要更改的足迹信息
        ShopHistory shopHistory = new ShopHistory();
        shopHistory.setId(snowUtil.snowId());
        shopHistory.setGoodsId(goodsId);
        shopHistory.setUserId(userId);
        shopHistory.setHistoryTime(new Date());

        // mybatis-plus,创建一个查询对象，提供好的，直接用
        QueryWrapper<ShopHistory> historyQueryWrapper = new QueryWrapper<>();
        // 用and拼接多条件查询语句
        historyQueryWrapper.and(wrapper -> wrapper.eq("goods_id",goodsId).eq("user_id",userId));

        // 数据库中不存在该流量记录时，直接插入足迹数据
        if (redisTemplate.opsForZSet().score("historyFoot" + ":" + userId,goodsId) == null && shopHistoryMapper.selectCount(historyQueryWrapper) == 0 ){

       // if (shopHistoryMapper.selectCount(historyQueryWrapper) == 0) {
            // 判断数据库和redis中的足迹信息是否已经达到上限 5，如果达到上限，则删除流量时间最早的数据，然后再插入新的数据
            if (redisTemplate.opsForZSet().size("historyFoot" + ":" + userId) == 5){

                // 已达到上限，获取到属于时间最早的value，方便数据库的删除
                Set<String> oldGoodsId = redisTemplate.opsForZSet().range("historyFoot" + ":" + userId,0,0);

                oldGoodsId.forEach(string -> {

                    // mybatis-plus,创建一个查询对象，提供好的，直接用
                    QueryWrapper<ShopHistory> historyQueryWrapper1 = new QueryWrapper<>();
                    // 用and拼接多条件查询语句
                    historyQueryWrapper1.and(wrapper -> wrapper.eq("goods_id",string).eq("user_id",userId));

                    // 删除数据库的足迹信息
                    shopHistoryMapper.delete(historyQueryWrapper1);

                });

                // 删除足迹时间最早的信息
                redisTemplate.opsForZSet().removeRange("historyFoot" + ":" + userId,0,0);


            }

            // 将足迹信息存入redis中
            redisTemplate.opsForZSet().add("historyFoot" + ":" + userId,goodsId,Double.parseDouble(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))));

            // 将新的不存在该商品的足迹信息，插入足迹（数据库）
            shopHistoryMapper.insert(shopHistory);

            return;
        }

        // 存在的便更新redis中的足迹信息，也不需要判断是否达到上限
        redisTemplate.opsForZSet().add("historyFoot" + ":" + userId,goodsId,Double.parseDouble(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))));

        // 存在该足迹的信息，更新足迹时间到最新（数据库）
        shopHistoryMapper.update(shopHistory,historyQueryWrapper);

    }

    @Override
    public PageSupport<ShopGoodsVO> selectHistoryList(Integer pageNo, Integer pageSize, String userId) {

        // 创建统一返回分页对象
        PageSupport<ShopGoodsVO> pageSupport = new PageSupport<>();

        // mybatis-plus,创建一个查询对象，提供好的，直接用
        QueryWrapper<ShopHistory> historyQueryWrapper = new QueryWrapper<>();
        // 添加在历史足迹列表中查询该用户的所有足迹信息
        historyQueryWrapper.eq("user_id",userId);
        historyQueryWrapper.orderByDesc("history_time");

        // 创建分页对象
        // 页码和条数的处理都由内在源码自动处理，不需要自己再手动处理
        Page<ShopHistory> historyPage = new Page<>(pageNo,pageSize);

        // 查询历史足迹的列表
        Page<ShopHistory> historyResultPage = shopHistoryMapper.selectPage(historyPage,historyQueryWrapper);

        // 添加分页的页码数据
        pageSupport.setPageNo(pageNo);
        pageSupport.setPageSize(pageSize);
        pageSupport.setTotalPage((int) historyResultPage.getPages());
        pageSupport.setTotalCount((int) historyResultPage.getTotal());

        log.info("--- 总条数：{} ---",historyResultPage.getTotal());
        log.info("--- 总页数：{} ---",historyResultPage.getPages());

        // 查询足迹信息对应的商品部分详情
        List<ShopGoods> shopGoodsList = historyResultPage.getRecords().stream().map(history -> {
            // 创建足迹对应的商品实体对象
            ShopGoods shopGoods = new ShopGoods();
            // 查询对应的商品信息
            String goodsId = history.getGoodsId();

            shopGoods = shopGoodsMapper.selectById(goodsId);
            return shopGoods;
        }).collect(Collectors.toList());

        // 处理返回的商品结果列表，将库存进行转换为描述
        List<ShopGoodsVO> shopGoodsVOList = shopGoodsList.stream().map(shopGoods -> {
            // 创建足迹对应的商品实体VO对象
            ShopGoodsVO shopGoodsVO = new ShopGoodsVO();

            // 拷贝实体属性
            BeanUtils.copyProperties(shopGoods,shopGoodsVO);
            // 处理状态说明（可以定义枚举，也可以自定义工具转换-switch）
            shopGoodsVO.setGoodsNumber(shopGoods.getGoodsNumber() > 0 ? shopGoods.getGoodsNumber().toString() : "已售罄");

            return shopGoodsVO;
        }).collect(Collectors.toList());

        log.info("--- 返回结果：{} ---",shopGoodsVOList.toString());

        pageSupport.setPageData(shopGoodsVOList);

        log.info("--- 返回总数：{} ---",pageSupport.getTotalCount());

        return pageSupport;
    }

    @Override
    public boolean deleteHistoryByIds(List<String> ids) {

        // 遍历足迹id，并达到删除足迹信息的效果
        ids.forEach(id -> {

            // 获取数据库中该id对应的商品详情
            ShopHistory shopHistory = shopHistoryMapper.selectById(id);

            // 删除redis中对应的足迹数据
            redisTemplate.opsForZSet().remove("historyFoot" + ":" + shopHistory.getUserId(),shopHistory.getGoodsId());

            // 再删除数据库中的足迹信息
            shopHistoryMapper.deleteById(id);

        });

        return true;
    }

    @Override
    public boolean deleteAllHistoryByUserId(String userId) {

        // mybatis-plus,创建一个查询对象，提供好的，直接用
        QueryWrapper<ShopHistory> historyQueryWrapper = new QueryWrapper<>();
        // 添加在历史足迹列表中查询该用户的所有足迹信息
        historyQueryWrapper.eq("user_id",userId);

        // 如果用户足迹列表中有足迹信息可以进行批量删除
        if (shopHistoryMapper.selectCount(historyQueryWrapper) > 0) {

            // 删除redis中全部的足迹
            redisTemplate.delete("historyFoot" + ":" + userId);

            // 该用户存在足迹信息，可以执行全部删除
            shopHistoryMapper.delete(historyQueryWrapper);

            return true;
        }

        // 没有足迹信息不执行删除，返回失败
        return false;
    }

}
